﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using CompileApp.Models;
using CompileApp.windows;
using Microsoft.Win32;

namespace CompileApp;

public partial class LexProgram : UserControl
{
    private Nfa? _nfa;

    private Dfa? _dfa;

    public List<Token> Tokens = new();

    public LexProgram()
    {
        InitializeComponent();

        GrammarFileButton.Click += ReadGrammarFileContent;
        SourceFileButton.Click += ReadSourceFileContent;

        NdButton.Click += DrawFa;

        SaveButton.Click += SaveToken;

        StartButton.Click += StartGenerate;
    }

    // 生成Token
    private void StartGenerate(object sender, RoutedEventArgs e)
    {
        if (_dfa == null)
        {
            MessageBox.Show("请输入文法文件");
            return;
        }

        string code = SourceFileContent.Text;
        if (code.Equals(""))
        {
            MessageBox.Show("请先输入代码文件");
            return;
        }

        Tokens.Clear();

        string start = "0";
        string node = start;
        int line = 1;
        for (int index = 0, begin = 0; index < code.Length; index++)
        {
            var tuple = new Tuple<string, string>(node, code[index].ToString());
            if (_dfa.Rules.ContainsKey(tuple))
            {
                node = _dfa.Rules[tuple];
                if (_dfa.EmptySet.Contains(node))
                {
                    if (index - begin > 0)
                    {
                        string item = code.Substring(begin, index - begin);
                        Token token = new Token(line / 2 + 1, Constant.FindType(item), item);
                        Tokens.Add(token);
                        begin = index;
                        index--;
                    }

                    node = start;
                }
            }
            else
            {
                string item = code.Substring(begin, index - begin);
                Token token = new Token(line / 2 + 1, Constant.FindType(item), item);
                Tokens.Add(token);
                begin = index + 1;
                Tokens.Add(new Token(line / 2 + 1, Constant.FindType(code[index].ToString()), code[index].ToString()));

                node = start;
            }
            
            if (code[index] == '\n')
            {
                line++;
            }
        }

        ResultBox.Clear();

        foreach (var token in Tokens)
        {
            ResultBox.AppendText(token.GetText());
        }
    }

    // 保存Token到文件
    private void SaveToken(object sender, RoutedEventArgs e)
    {
        SaveFileDialog dialog = new SaveFileDialog();
        dialog.FileName = "课设程序生成的token文件.txt";
        dialog.Filter = "所有文件(*.*)|*.*";
        if (dialog.ShowDialog() ?? false)
        {
            File.WriteAllText(dialog.FileName, ResultBox.Text);
        }
    }

    // 阅读文法生成NFA和DFA
    private void ReadGrammarFileContent(object sender, RoutedEventArgs args)
    {
        TextBox? content = GrammarFileContent;

        OpenFileDialog fileDialog = new OpenFileDialog();
        fileDialog.Title = "请选择文件";
        fileDialog.Filter = "所有文件(*.*)|*.*";
        if (fileDialog.ShowDialog() ?? false)
        {
            content.Clear();
            string fileName = fileDialog.FileName;
            StreamReader reader = new StreamReader(fileName);
            string? line = reader.ReadLine();
            while (line != null)
            {
                content.AppendText($"{line}\n");
                line = reader.ReadLine();
            }

            reader.Close();
            string grammarText = content.Text.Replace(" ", "");
            _nfa = new Nfa(grammarText);
            _dfa = new Dfa(_nfa);
            // ResultBox.Text = grammarText.Replace(" ", "");
            // Grammar grammar = new Grammar(grammarText.Replace(" ", ""));
            // ResultBox.Text = grammar.ConvertToRegularExpression();
        }
        else
        {
            // MessageBox.Show("已取消!");
        }
    }

    // 阅读源代码
    private void ReadSourceFileContent(object sender, RoutedEventArgs args)
    {
        TextBox? content = SourceFileContent;

        OpenFileDialog fileDialog = new OpenFileDialog();
        fileDialog.Title = "请选择文件";
        fileDialog.Filter = "所有文件(*.*)|*.*";
        if (fileDialog.ShowDialog() ?? false)
        {
            content.Clear();
            string fileName = fileDialog.FileName;
            StreamReader reader = new StreamReader(fileName);
            string? line = reader.ReadLine();
            while (line != null)
            {
                content.AppendText($"{line}\n");
                line = reader.ReadLine();
            }

            reader.Close();
        }
        else
        {
            // MessageBox.Show("已取消!");
        }
    }

    // 显示NFA和DFA
    private void DrawFa(object sender, RoutedEventArgs args)
    {
        if (_nfa == null || _dfa == null)
        {
            MessageBox.Show("未输入文法文件");
            return;
        }

        ShowFA showFa = new ShowFA(_nfa, _dfa);
        showFa.Show();
    }
}

public struct Token
{
    public int Line;

    public string Type;

    public string Value;

    public Token(int line, string type, string value)
    {
        Line = line;
        Type = type;
        Value = value;
    }

    public string GetText()
    {
        if (!Constant.IsValid(Value))
        {
            return "";
        }

        // string result = Convert.ToString(Line).PadRight(9, ' ') + Type.PadRight(15, ' ') + Value + "\n";
        string t = Value;
        if (t == "\t")
        {
            t = "制表符";
        }
        else if (t == "\n")
        {
            t = "换行";
        }
        else if (string.IsNullOrWhiteSpace(t))
        {
            t = "空格";
        }

        string result = $"({Line}\t{Type}\t{t})\n";

        return result;
    }
    
    
}